package com.web_bloks.document.client;

import com.google.gwt.core.client.GWT;

//import com.web_bloks.system.client.Logger;

/**
 * Title
 *	A 'Title' is composed by:  NAMESPACE:NAME
 *  Don't forget to CONFIGURE !
 *  
 * @author Jean-Lou Dupont
 *
 */
public class Title {

	final static String thisClass ="com.web_bloks.document.client.Title";
	
	public enum Code {
		WILD, NORMAL 
	}
	
	Code cName          = Code.NORMAL;
	
	String name 		= null;
	Namespace namespace	= null;

	static Namespaces namespaces = null;
	
	/*===================================================================
	 * CONSTRUCTORS 
	 ===================================================================*/
	protected Title() {
		super();
	}
	
	protected Title( Namespace namespace, String name) {
		super();
		//Logger.logInfo(thisClass+".Title(): domain["+namespace.getDomainId()+"] namespace["+namespace.getName()+"] name["+name+"]");
		this.name = new String( name );
		this.namespace = namespace;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setNamespace(Namespace ns) {
		this.namespace = ns;
	}
	public void setWild() {
		this.cName = Code.WILD;
	}
	/*===================================================================
	 * CONFIGURATION
	 ===================================================================*/
	public static void setNamespaces(Namespaces nss){
		namespaces = nss;
	}
	
	/*===================================================================
	 * BUILDERS
	 ===================================================================*/
	public Title getRawTitle() throws TitleException, NamespaceException {
		Namespace nsraw = Namespace.createRaw( this.namespace );
		
		return newFromText( nsraw + ":" + this.name );
	}
	
	/**
	 * Creates a 'wild' title i.e. [_wild_;_wild_]
	 * 
	 * @return Title
	 */
	public static Title newWild() {
		
		Namespace ns = Namespace.createWild();
		return build( ns, getWildComponent() );
	}
	
	public static Title newWild(Namespace ns) {

		if ( null == ns )
			throw new RuntimeException( thisClass+".newWild: ns can't be null" );

		return build( ns, getWildComponent() );
	}
	
	public static Title newFromText(String text) throws TitleException, NamespaceException {
		
		if ( null == text )
			throw new RuntimeException( thisClass+".newFromText: text can't be null" );
		
		String[] parts = text.split(":");
		
		String ns   = null;
		String name = null;
		
		switch( parts.length ) {

			// name
			case 1:
					ns   = new String();				
					name = new String( parts[0] );
					break;
					
			// ns:name
			case 2: 
					ns   = new String( parts[0] );
					name = new String( parts[1] );
					break;

			case 0:					
			default:
					throw new TitleException(thisClass+".newFromText: error building title from 'text' ");
		}

		Namespace n = Namespace.create(ns);
		
		return build(n, name);
	}
	public static Title safeNewFromText(String text) {
		try {
			return Title.newFromText(text);
		} catch(TitleException te) {
			throw new RuntimeException( "safeNewFromText EXCEPTION, text="+text );
		} catch(NamespaceException ne) {
			throw new RuntimeException( "safeNewFromText EXCEPTION, text="+text );
		}
	}
	/**
	 * 
	 * @param namespace
	 * @param name
	 * @return Title
	 * @throws NamespaceException
	 */
	public static Title newFromParts(Namespace namespace, String name) throws NamespaceException {
		validateNamespace( namespace );
		return build(namespace, name);
	}
	
	protected static Title build( Namespace ns, String name ) {
		Title t = (Title) GWT.create(Title.class);
		t.setNamespace(ns);
		t.setName(name);
		
		if (isWildComponent(name))
			t.setWild();
		
		return t;
	}
	/*===================================================================
	 * API
	 ===================================================================*/
	/**
	 * Used to validate the Title when it is constructed
	 * from an untrusted source, to make sure that no 'wild' title
	 * is created.
	 */
	public boolean isNormal() {
		return (cName == Code.NORMAL && namespace.isNormal() );
	}
	/**
	 * If either component is WILD, then WILD it is
	 */
	public boolean isWild() {
		return (cName == Code.WILD || namespace.isWild() );
	}
	public boolean isWildNamespace(){
		return namespace.isWild();
	}
	public boolean isWildName() {
		return cName == Code.WILD;		
	}
	
	public String getName() {
		return name;
	}
	public Namespace getNamespace() {
		return namespace;
	}
	
	public String toString() {
		
		if (namespace == null)
			return name;
		if (namespace.getName() == null)
			return name;
		if (namespace.getName().length() == 0)
			return name;
		
		return namespace+":"+name;
	}
	/**
	 * 
	 * @return boolean result
	 */
	public boolean validate() {
		
		if (( null == name ) || (null == namespace))
			return false;
		
		boolean result = true; //optimistic
		try {
			Title.validateNamespace(namespace);
		} catch(NamespaceException e) {
			result = false;
		}
		
		return result;
	}
	
	/*===================================================================
	 * HELPERS
	 ===================================================================*/
	/**
	 * 
	 */
	private static String validateNamespace(Namespace ns) throws NamespaceException {
		return validateNamespace( ns.getName() );
	}
	/**
	 * 
	 * @param name
	 * @return nsid
	 * @throws NamespaceException
	 */
	private static String validateNamespace(String name) throws NamespaceException {
		//Logger.logInfo(thisClass+".validateNamespace: name["+name+"]");
			
		String nsid = namespaces.lookup(name);
		
		if (null == nsid)
			throw new NamespaceException(thisClass+".validateNamespace: invalid namespace, name["+name+"]");
		
		return nsid;
	}
	
	private static boolean isWildComponent(String str) {
		
		if (null==str)
			throw new RuntimeException(thisClass+".isWild: input can't be null");
		
		return ( str == "*" );
	}

	private static String getWildComponent() {
		return "*";
	}
	/*===================================================================
	 * Overrides
	 ===================================================================*/
	/*
	 */
	public boolean equals(Object t) {

		// shortcut
		Title tc = (Title) t;
		
		//Logger.logDebug(this.getClass()+".equals: title1["+this+"] title2["+tc+"]");
		
		if (!( t instanceof Title ))
			throw new RuntimeException(this.getClass()+".equals: unsupported comparison");
		
	
		if ( tc.cName != this.cName ) return false;
		if ( tc.name  != this.name  ) return false;
		if ( tc.namespace != this.namespace ) return false;
		
		return true;
	}

}//END